package com.example.project.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.project.annotation.FieldMeta;

/**
 * 注解工具类
 * 提供注解相关的工具方法
 * 
 * @author wangxu
 * @date 2025/10/10
 */
public class AnnotationUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(AnnotationUtil.class);

    /**
     * 获取字段上的指定注解
     * 
     * @param field 字段
     * @param annotationClass 注解类
     * @param <T> 注解类型
     * @return 注解实例，如果不存在返回null
     */
    public static <T extends Annotation> T getAnnotation(Field field, Class<T> annotationClass) {
        if (field == null || annotationClass == null) {
            return null;
        }
        return field.getAnnotation(annotationClass);
    }

    /**
     * 检查字段是否包含指定注解
     * 
     * @param field 字段
     * @param annotationClass 注解类
     * @return 是否包含注解
     */
    public static boolean hasAnnotation(Field field, Class<? extends Annotation> annotationClass) {
        return getAnnotation(field, annotationClass) != null;
    }

    /**
     * 获取对象所有字段的指定注解信息
     * 
     * @param obj 对象
     * @param annotationClass 注解类
     * @param <T> 注解类型
     * @return 字段名到注解的映射
     */
    public static <T extends Annotation> Map<String, T> getFieldAnnotations(Object obj, Class<T> annotationClass) {
        Map<String, T> annotations = new HashMap<>();
        if (obj == null || annotationClass == null) {
            return annotations;
        }
        
        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                T annotation = field.getAnnotation(annotationClass);
                if (annotation != null) {
                    annotations.put(field.getName(), annotation);
                }
            }
        } catch (Exception e) {
            logger.error("获取字段注解失败: {}", e.getMessage());
        }
        return annotations;
    }

    /**
     * 获取对象所有包含指定注解的字段名
     * 
     * @param obj 对象
     * @param annotationClass 注解类
     * @return 字段名列表
     */
    public static List<String> getAnnotatedFieldNames(Object obj, Class<? extends Annotation> annotationClass) {
        List<String> fieldNames = new ArrayList<>();
        if (obj == null || annotationClass == null) {
            return fieldNames;
        }
        
        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.getAnnotation(annotationClass) != null) {
                    fieldNames.add(field.getName());
                }
            }
        } catch (Exception e) {
            logger.error("获取注解字段名失败: {}", e.getMessage());
        }
        return fieldNames;
    }

    /**
     * 根据FieldMeta注解验证字段值
     * 
     * @param obj 对象
     * @param fieldName 字段名
     * @return 验证结果，空字符串表示验证通过
     */
    public static String validateFieldByMeta(Object obj, String fieldName) {
        if (obj == null || fieldName == null) {
            return "对象或字段名不能为空";
        }
        
        try {
            Class<?> clazz = obj.getClass();
            Field field = clazz.getDeclaredField(fieldName);
            FieldMeta meta = field.getAnnotation(FieldMeta.class);
            
            if (meta == null) {
                return ""; // 没有注解，不验证
            }
            
            field.setAccessible(true);
            Object value = field.get(obj);
            
            // 必填验证
            if (meta.required() && (value == null || value.toString().trim().isEmpty())) {
                return StringUtils.isNotBlank(meta.message()) ? meta.message() : 
                       StringUtils.isNotBlank(meta.name()) ? meta.name() + "不能为空" : "字段不能为空";
            }
            
            // 长度验证
            if (meta.maxLength() > 0 && value != null) {
                String strValue = value.toString();
                if (strValue.length() > meta.maxLength()) {
                    return StringUtils.isNotBlank(meta.message()) ? meta.message() : 
                           StringUtils.isNotBlank(meta.name()) ? meta.name() + "长度不能超过" + meta.maxLength() + "个字符" : 
                           "字段长度不能超过" + meta.maxLength() + "个字符";
                }
            }
            
            // 数值范围验证
            if (value instanceof Number) {
                double numValue = ((Number) value).doubleValue();
                if (numValue < meta.minValue()) {
                    return StringUtils.isNotBlank(meta.message()) ? meta.message() : 
                           StringUtils.isNotBlank(meta.name()) ? meta.name() + "不能小于" + meta.minValue() : 
                           "字段值不能小于" + meta.minValue();
                }
                if (numValue > meta.maxValue()) {
                    return StringUtils.isNotBlank(meta.message()) ? meta.message() : 
                           StringUtils.isNotBlank(meta.name()) ? meta.name() + "不能大于" + meta.maxValue() : 
                           "字段值不能大于" + meta.maxValue();
                }
            }
            
            // 正则表达式验证
            if (StringUtils.isNotBlank(meta.pattern()) && value != null) {
                String strValue = value.toString();
                if (!strValue.matches(meta.pattern())) {
                    return StringUtils.isNotBlank(meta.message()) ? meta.message() : 
                           StringUtils.isNotBlank(meta.name()) ? meta.name() + "格式不正确" : "字段格式不正确";
                }
            }
            
        } catch (Exception e) {
            logger.error("字段验证失败: {}", e.getMessage());
            return "字段验证异常";
        }
        
        return ""; // 验证通过
    }

    /**
     * 获取字段的显示名称（优先使用FieldMeta注解的name属性）
     * 
     * @param field 字段
     * @return 显示名称
     */
    public static String getFieldDisplayName(Field field) {
        if (field == null) {
            return "";
        }
        
        FieldMeta meta = field.getAnnotation(FieldMeta.class);
        if (meta != null && StringUtils.isNotBlank(meta.name())) {
            return meta.name();
        }
        
        // 如果没有注解，使用字段名（首字母大写）
        String fieldName = field.getName();
        return fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }

    /**
     * 获取对象所有字段的元数据信息
     * 
     * @param obj 对象
     * @return 字段名到元数据的映射
     */
    public static Map<String, Map<String, Object>> getFieldMetaInfo(Object obj) {
        Map<String, Map<String, Object>> metaInfo = new HashMap<>();
        if (obj == null) {
            return metaInfo;
        }
        
        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                FieldMeta meta = field.getAnnotation(FieldMeta.class);
                if (meta != null) {
                    Map<String, Object> info = new HashMap<>();
                    info.put("name", meta.name());
                    info.put("description", meta.description());
                    info.put("required", meta.required());
                    info.put("type", meta.type());
                    info.put("maxLength", meta.maxLength());
                    info.put("showInList", meta.showInList());
                    info.put("showInForm", meta.showInForm());
                    info.put("searchable", meta.searchable());
                    info.put("order", meta.order());
                    
                    metaInfo.put(field.getName(), info);
                }
            }
        } catch (Exception e) {
            logger.error("获取字段元数据失败: {}", e.getMessage());
        }
        return metaInfo;
    }
}